home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / pinfocom_3_0.lha / Source / amiga.c < prev    next >
Text File  |  1992-10-22  |  62KB  |  2,667 lines

  1. /* amiga.c
  2.  *
  3.  *  ``pinfocom'' -- a portable Infocom Inc. data file interpreter.
  4.  *  Copyright (C) 1987-1992  InfoTaskForce
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; see the file COPYING.  If not, write to the
  18.  *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * $Header: RCS/amiga.c,v 3.0 1992/10/21 16:56:19 pds Stab $
  23.  */
  24.  
  25. /*
  26.  *  Amiga    terminal  interface  created  by  Olaf  `Olsen' Barthel, send
  27.  *  complaints and bug reports to:
  28.  *
  29.  *         Olaf `Olsen' Barthel
  30.  *         Brabeckstrasse 35
  31.  *         D-3000 Hannover 71
  32.  *
  33.  *         Federal Republic of Germany
  34.  *
  35.  *  EMail: olsen@sourcery.mxm.sub.org
  36.  *
  37.  *  This  interface has been designed to work on any Amiga machine running
  38.  *  Kickstart  1.2   or  higher.   Unlike the original Infocom interpreter
  39.  *  interfaces,  it  supports command-line history (20 lines are standard,
  40.  *  the  value  can  be changed at compile-time) and command-line editing.
  41.  *  Editing functions are as follows:
  42.  *
  43.  *  - Backspace
  44.  *
  45.  *    Deletes the character to the left of the cursor.
  46.  *
  47.  *  - Shift + Backspace
  48.  *
  49.  *    Deletes everything from the cursor backward to the start of the line.
  50.  *
  51.  *  - Delete
  52.  *
  53.  *    Deletes the character under the cursor.
  54.  *
  55.  *  - Shift + Delete
  56.  *
  57.  *    Deletes everything from the cursor forward to the end of the line.
  58.  *
  59.  *  - Control + X
  60.  *
  61.  *    Deletes the entire line contents.
  62.  *
  63.  *  - Control + \
  64.  *
  65.  *    Closes the window.
  66.  *
  67.  *  - Control + A
  68.  *
  69.  *    Moves the cursor to the start of the line.
  70.  *
  71.  *  - Control + Z
  72.  *
  73.  *    Moves the cursor to the end of the line.
  74.  *
  75.  *  - Control + W
  76.  *
  77.  *    Deletes the word to the left of the cursor.
  78.  *
  79.  *  - Control + K
  80.  *
  81.  *    Deletes everything from the cursor forward to the end of the line.
  82.  *
  83.  *  - Control + U
  84.  *
  85.  *    Deletes everything from the cursor backward to the start of the line.
  86.  *
  87.  *  - Control + C
  88.  *
  89.  *    Remembers current input line contents.
  90.  *
  91.  *  - Control + Y
  92.  *
  93.  *    Undoes previous editing operation.
  94.  *
  95.  *  - Cursor up
  96.  *
  97.  *    Recalls previous history line.
  98.  *
  99.  *  - Shift + Cursor up
  100.  *
  101.  *    Recalls first history line.
  102.  *
  103.  *  - Cursor down
  104.  *
  105.  *    Moves to next history line.
  106.  *
  107.  *  - Shift + Cursor down
  108.  *
  109.  *    Moves to last history line.
  110.  *
  111.  *  - Cursor right
  112.  *
  113.  *    Moves the cursor to the right.
  114.  *
  115.  *  - Shift + Cursor right
  116.  *
  117.  *    Moves the cursor to the end of the line.
  118.  *
  119.  *  - Cursor left
  120.  *
  121.  *    Moves the cursor to the left.
  122.  *
  123.  *  - Shift + Cursor left
  124.  *
  125.  *    Moves the cursor to the beginning of the line.
  126.  *
  127.  *  - Help
  128.  *
  129.  *    Starts  function key assignment.  Press the function key you wish to
  130.  *    assign  text  to, then enter the text you wish to use.  The vertical
  131.  *    bar (|) and exclamation mark (!) serve  as line terminators and will
  132.  *    produce a carriage-return when the key assigment is recalled.
  133.  *
  134.  *  - F1-F10, Shift + F1-F10
  135.  *
  136.  *    Recalls function key assignment.
  137.  *
  138.  *  - Numeric keypad
  139.  *
  140.  *    Produces movement commands.
  141.  *
  142.  *  As  for  tool  and  project  icons the following tool type entries are
  143.  *  supported.   Note  that due to a bug in icon.library v1.2 and v1.3 the
  144.  *  single line tool types such as "CUSTOMSCREEN" will have to be followed
  145.  *  by a `=' character (e.g.  "CUSTOMSCREEN=").
  146.  *
  147.  *  - FILETYPE
  148.  *
  149.  *    This  is  where  you  or  the  interpreter  places  the  type of the
  150.  *    corresponding   file.    For   saved   game   files   this  will  be
  151.  *    "FILETYPE=BOOKMARK|ITF",  for  story  files "FILETYPE=STORY" and for
  152.  *    transcript files "FILETYPE=TEXT|ASCII".
  153.  *
  154.  *  - CUSTOMSCREEN
  155.  *
  156.  *    Corresponds to the "-C" command-line option, i.e.  the output window
  157.  *    will  be  opened  on  a  custom  screen rather than on the Workbench
  158.  *    screen.   The screen will inherit attributes such as depth, colours,
  159.  *    size   and  display  mode  from  the  Workbench  screen.   The  only
  160.  *    difference  is  the handling of A2024 screen modes, which will cause
  161.  *    the screen to open in hires-interlaced display mode.
  162.  *       If  running  under operating system revisions previous to v2.04 a
  163.  *    monochrome display with the background and text colours set to black
  164.  *    and white will be opened.
  165.  *
  166.  *  - TEXTFONT
  167.  *
  168.  *    Corresponds  to the "-F" option, i.e.  determines the text rendering
  169.  *    font  to  be used.  This will be a disk-resident proportional-spaced
  170.  *    font.  If this option is specified "LISTFONT" and "FONTSIZE" have to
  171.  *    be   included   as   well.    To  use  the  Adobe  Times  font,  use
  172.  *    "TEXTFONT=Times".
  173.  *
  174.  *  - LISTFONT
  175.  *
  176.  *    Corresponds  to the "-L" option, i.e.  determines the list and table
  177.  *    rendering font to be used.  This will be a disk-resident fixed-width
  178.  *    font.  If this option is specified "TEXTFONT" and "FONTSIZE" have to
  179.  *    be   included   as  well.   To  use  the  Adobe  Courier  font,  use
  180.  *    "LISTFONT=Courier".
  181.  *
  182.  *  - FONTSIZE
  183.  *
  184.  *    Corresponds to the "-S" option, i.e.  the point size of the text and
  185.  *    list fonts specified using the "TEXTFONT" and "LISTFONT" tool types.
  186.  *    To use point size 11, use "FONTSIZE=11".
  187.  *
  188.  *  - STORY
  189.  *
  190.  *    This  tool  type  entry  determines  the  story  file  to  be  used.
  191.  *    Typically, it is saved in the project icon of a saved game file.  In
  192.  *    order  to  use  "Work:Infocom/ZorkIII/Story.Data"  as  a story file,
  193.  *    enter the following text:  "STORY=Work:Infocom/ZorkIII/Story.Data".
  194.  *
  195.  *  - ATTRIBUTEASSIGNMENTS
  196.  *
  197.  *    Corresponds to the "-a" command-line option.
  198.  *
  199.  *  - ATTRIBUTETESTS
  200.  *
  201.  *    Corresponds to the "-A" command-line option.
  202.  *
  203.  *  - CONTEXT
  204.  *
  205.  *    Corresponds  to  the  "-c" command-line option.  In order to use two
  206.  *    lines of inter-page context, use "CONTEXT=2".
  207.  *
  208.  *  - ECHO
  209.  *
  210.  *    Corresponds to the "-e" command-line option.
  211.  *
  212.  *  - INDENT
  213.  *
  214.  *    Corresponds  to  the  "-i" command-line option.  In order to use two
  215.  *    characters of line indent, use "INDENT=2".
  216.  *
  217.  *  - MARGIN
  218.  *
  219.  *    Corresponds  to  the  "-m" command-line option.  In order to use two
  220.  *    characters as a line margin, use "MARGIN=2".
  221.  *
  222.  *  - NOPAGER
  223.  *
  224.  *    Corresponds to the "-p" command-line option.
  225.  *
  226.  *  - PROMPT
  227.  *
  228.  *    Corresponds to the "-P" command-line option.
  229.  *
  230.  *  - NOSTATUS
  231.  *
  232.  *    Corresponds to the "-s" command-line option.
  233.  *
  234.  *  - TRANSFERS
  235.  *
  236.  *    Corresponds to the "-t" command-line option.
  237.  *
  238.  *  - TANDY
  239.  *
  240.  *    Corresponds to the "-T" command-line option.
  241.  *
  242.  *  This   interpreter   supports  proportional  fonts:   by  default  the
  243.  *  Workbench  screen  font  will  be  used  for text display (this can be
  244.  *  overridden  using  the  "TEXTFONT",  "LISTFONT"  and  "FONTSIZE"  tool
  245.  *  types).  If the Workbench screen font and the system font do not match
  246.  *  in  height the system font will be used for text display.  This is due
  247.  *  to  the  fact  that  the  interpreter  contains conditional code which
  248.  *  changes  the type of the font during the game if tables or maps are to
  249.  *  be displayed.
  250.  *
  251.  *  If  you  want the interpreter to save icons with saved game files make
  252.  *  sure  that  the icon file "Icon.Data" is present in the directory from
  253.  *  which  the  interpreter was loaded or saved game files will be created
  254.  *  without getting icons attached.
  255.  *     The  interpreter  recognizes  saved  game  files  by their filetype
  256.  *  entries,  i.e.   the  tooltype  "FILETYPE=BOOKMARK" has to be present.
  257.  *  Function  key  assignments,  the name of the story file being used and
  258.  *  game  options  are  saved along with the game file icon.  Function key
  259.  *  assignments  are  restored  automatically  when  a  saved game file is
  260.  *  loaded.   Story  file  name  and  options  are  considered only if the
  261.  *  interpreter is invoked by double-clicking on a project icon.
  262.  *
  263.  *
  264.  *  The  following  list  of  features is valid only for Kickstart 2.04 or
  265.  *  higher.   Users  whose  machines run Kickstart 1.2 or 1.3 will have to
  266.  *  get along with a slightly simplified interface.
  267.  *
  268.  *  - Several  options  and  commands  can be changed via pull-down menus.
  269.  *    Game   files  can  be  restored  by  dropping  their  icons  on  the
  270.  *    interpreter window.
  271.  *
  272.  *  - If  run  from  Workbench  with no story file available the interface
  273.  *    will  check  the  "Infocom:" assignment or volume if present.  If it
  274.  *    cannot  be  found a file requester will allow you to select the game
  275.  *    file to use.  If present the "Infocom:" volume or assignment will be
  276.  *    scanned for valid type 3 Infocom game files.  If more than one valid
  277.  *    game file is found a list will be displayed to choose from.
  278.  *
  279.  *  - The  interface  also  supports  multi-volume assignments, so you can
  280.  *    assign  "Infocom:" to multiple directories the interface is to scan.
  281.  *    One  example  how  to use it would be to copy the "Lost Treasures of
  282.  *    Infocom"  to your hard disk and then use the "Assign Infocom:  <Game
  283.  *    directory> Add" command for each game file directory.
  284.  *
  285.  *
  286.  *  Some things which you might want to know about:
  287.  *
  288.  *  - Clipboard  support  has been implemented in so far as it is possible
  289.  *    to  paste  the  contents of the clipboard, but there is no option to
  290.  *    copy  the screen text to the clipboard.  This may follow in a future
  291.  *    release  version  since  it  requires  a  good  lot  of work.  Paste
  292.  *    operations  are  limited  to  a single line of input, any additional
  293.  *    text  is  discarded.   Line  feeds  are automatically converted into
  294.  *    carriage  returns.   Any  non-printable  characters are filtered out
  295.  *    while reading.
  296.  *
  297.  *  - As of this writing, the interface ignores any page length settings.
  298.  *
  299.  *  - If  a  fixed  text window is displayed (such as by `Seastalker') the
  300.  *    status line will be enabled by default.  If the fixed text window is
  301.  *    disabled  again the interface will pay attention to the user-defined
  302.  *    settings.
  303.  *
  304.  *  - Due   to  the  current  implementation  of  pull-down-menu  support,
  305.  *    drag-selection and multiple-selection are not supported.
  306.  *
  307.  *  Please  refer to the `COPYING' file for distribution conditions and to
  308.  *  the `pinfo.txt' file for a general list of features and command-line
  309.  *  options.
  310.  *
  311.  *
  312.  *  In  order  to  compile  this program an ANSI compliant `C' compiler is
  313.  *  required.   I  recommend  using the GNU `C' compiler which I also used
  314.  *  for development.
  315.  *
  316.  *  May the source be with you,
  317.  *                              -olsen
  318.  */
  319.  
  320. #ifndef _AMIGA_GLOBAL_H
  321. #include "amiga_global.h"
  322. #endif    /* !_AMIGA_GLOBAL_H */
  323.  
  324.     /* Disable ^C trapping for several Amiga `C' compilers. */
  325.  
  326. #ifdef LATTICE
  327. ULONG CXBRK(VOID) { return(0); }
  328. #endif    /* LATTICE */
  329.  
  330. #ifdef AZTEC_C
  331. long Chk_Abort(VOID) { return(0); }
  332. #endif    /* AZTEC_C */
  333.  
  334. /*
  335.  * Global Variables
  336.  */
  337.  
  338. /*
  339.  * Variable:    scr_usage
  340.  *
  341.  * Description:
  342.  *      This variable should contain a usage string for any extra
  343.  *      command-line options available through this terminal
  344.  *      interface.
  345.  */
  346.  
  347. const char *scr_usage       = "[-C] [-L list font name] [-F text font name] [-S font point size]";
  348.  
  349. /*
  350.  * Variable:    scr_long_usage
  351.  *
  352.  * Description:
  353.  *      This variable should contain a more verbose usage string
  354.  *      detailing the command-line options available through this
  355.  *      terminal interface, one option per line.
  356.  */
  357.  
  358. const char *scr_long_usage  = "\t-C\topen custom screen\n\t-L name\tset name of list font\n\t-F name\tset name of text font\n\t-S #\tset font point size\n";
  359.  
  360. /*
  361.  * Variable:    scr_opt_list
  362.  *
  363.  * Description:
  364.  *      This variable should contain a getopt(3)-style option list for
  365.  *      any command-line options available through this terminal
  366.  *      interface.
  367.  */
  368.  
  369. const char *scr_opt_list    = "CL:F:S:";
  370.  
  371. /*
  372.  * Function:    scr_cmdarg()
  373.  *
  374.  * Arguments:
  375.  *      argc        number of original arguments
  376.  *      argvp       pointer to array of strings containing args
  377.  *
  378.  * Returns:
  379.  *      Number of new arguments.
  380.  *
  381.  * Description:
  382.  *      This function is called before any command line parsing is
  383.  *      done.  Any terminal interface-specific arguments should be
  384.  *      pulled out of the argv list and any extra arguments obtained
  385.  *      from resource files or wherever should be added.  Note that
  386.  *      (*argvp)[0] must be the command name and (*argvp)[argc] must
  387.  *      be a null pointer.
  388.  *
  389.  * Notes:
  390.  */
  391.  
  392. int
  393. scr_cmdarg(int argc, char ***argvp)
  394. {
  395.         /* Obtain current process pointer. */
  396.  
  397.     ThisProcess = (struct Process *)FindTask(NULL);
  398.  
  399.         /* Are we running as a child of Workbench? */
  400.  
  401.     if(!argc)
  402.     {
  403.         STATIC char    *DummyInput[19];
  404.  
  405.         char         ProjectName[MAX_FILENAME_LENGTH],
  406.                  StoryName[MAX_FILENAME_LENGTH];
  407.         int         Count = 0;
  408.  
  409.             /* Clear the names. */
  410.  
  411.         ProjectName[0] = StoryName[0] = 0;
  412.  
  413.             /* Obtain Workbench startup message. */
  414.  
  415.         WBenchMsg = (struct WBStartup *)*argvp;
  416.  
  417.             /* Install new input data. */
  418.  
  419.         *argvp = (char **)DummyInput;
  420.  
  421.             /* Fill in the program name. */
  422.  
  423.         DummyInput[Count++] = WBenchMsg -> sm_ArgList[0] . wa_Name;
  424.  
  425.             /* Open system libraries, we will
  426.              * need the icon.library routines.
  427.              */
  428.  
  429.         if(ConOpenLibs())
  430.         {
  431.                 /* Did we succeed in opening icon.library? */
  432.  
  433.             if(IconBase)
  434.             {
  435.                 LONG i;
  436.  
  437.                     /* Run down the list of arguments... */
  438.  
  439.                 for(i = 0 ; Count < 16 && i < WBenchMsg -> sm_NumArgs ; i++)
  440.                 {
  441.                         /* A correct project icon always has a
  442.                          * directory lock associated, let's check it.
  443.                          */
  444.  
  445.                     if(WBenchMsg -> sm_ArgList[i] . wa_Lock && WBenchMsg -> sm_ArgList[i] . wa_Name)
  446.                     {
  447.                         struct DiskObject *Icon;
  448.  
  449.                             /* Skip to the icon location. */
  450.  
  451.                         CurrentDir(WBenchMsg -> sm_ArgList[i] . wa_Lock);
  452.  
  453.                             /* Try to read the project icon. */
  454.  
  455.                         if(Icon = GetDiskObject(WBenchMsg -> sm_ArgList[i] . wa_Name))
  456.                         {
  457.                                 /* Is it a project icon or even the
  458.                                  * program icon itself?
  459.                                  */
  460.  
  461.                             if(Icon -> do_Type == WBPROJECT || (!i && Icon -> do_Type == WBTOOL))
  462.                             {
  463.                                 STRPTR Type;
  464.  
  465.                                     /* Find the file type if any. */
  466.  
  467.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"FILETYPE"))
  468.                                 {
  469.                                         /* Is it a bookmark file? */
  470.  
  471.                                     if(MatchToolValue(Type,"BOOKMARK") && MatchToolValue(Type,"ITF"))
  472.                                         strcpy(ProjectName,WBenchMsg -> sm_ArgList[i] . wa_Name);
  473.  
  474.                                         /* Is it a story file? */
  475.  
  476.                                     if(MatchToolValue(Type,"STORY"))
  477.                                         strcpy(StoryName,WBenchMsg -> sm_ArgList[i] . wa_Name);
  478.                                 }
  479.  
  480.                                     /* Are we to use a special text rendering font? */
  481.  
  482.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"TEXTFONT"))
  483.                                     strcpy(TextFontName,Type);
  484.  
  485.                                     /* Are we to use a special list text rendering font? */
  486.  
  487.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"LISTFONT"))
  488.                                     strcpy(ListFontName,Type);
  489.  
  490.                                     /* Which font size are we to use? */
  491.  
  492.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"FONTSIZE"))
  493.                                     FontSize = atoi(Type);
  494.  
  495.                                     /* Are we to use a special story file? */
  496.  
  497.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"STORY"))
  498.                                     strcpy(StoryName,Type);
  499.  
  500.                                     /* Are we to open a custom screen? */
  501.  
  502.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"CUSTOMSCREEN"))
  503.                                     UseCustomScreen = TRUE;
  504.  
  505.                                     /* Are we to print object attribute assignments while playing? */
  506.  
  507.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"ATTRIBUTEASSIGNMENTS"))
  508.                                     DummyInput[Count++] = "-a";
  509.  
  510.                                     /* Are we to print object attribute tests while playing? */
  511.  
  512.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"ATTRIBUTETESTS"))
  513.                                     DummyInput[Count++] = "-A";
  514.  
  515.                                     /* Are we to set the page context? */
  516.  
  517.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"CONTEXT"))
  518.                                 {
  519.                                     DummyInput[Count++] = "-c";
  520.  
  521.                                     if(DummyInput[Count] = (STRPTR)malloc(strlen(Type) + 1))
  522.                                         strcpy(DummyInput[Count++],Type);
  523.                                     else
  524.                                         Count--;
  525.                                 }
  526.  
  527.                                     /* Are we to set the line indent? */
  528.  
  529.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"INDENT"))
  530.                                 {
  531.                                     DummyInput[Count++] = "-i";
  532.  
  533.                                     if(DummyInput[Count] = (STRPTR)malloc(strlen(Type) + 1))
  534.                                         strcpy(DummyInput[Count++],Type);
  535.                                     else
  536.                                         Count--;
  537.                                 }
  538.  
  539.                                     /* Are we to set the line margin? */
  540.  
  541.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"MARGIN"))
  542.                                 {
  543.                                     DummyInput[Count++] = "-m";
  544.  
  545.                                     if(DummyInput[Count] = (STRPTR)malloc(strlen(Type) + 1))
  546.                                         strcpy(DummyInput[Count++],Type);
  547.                                     else
  548.                                         Count--;
  549.                                 }
  550.  
  551.                                     /* Are we to echo line input? */
  552.  
  553.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"ECHO"))
  554.                                     DummyInput[Count++] = "-e";
  555.  
  556.                                     /* Are we to disable text paging? */
  557.  
  558.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"NOPAGER"))
  559.                                     DummyInput[Count++] = "-p";
  560.  
  561.                                     /* Are we to display the alternate prompt, if any? */
  562.  
  563.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"PROMPT"))
  564.                                     DummyInput[Count++] = "-P";
  565.  
  566.                                     /* Are we to disable the status line? */
  567.  
  568.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"NOSTATUS"))
  569.                                     DummyInput[Count++] = "-s";
  570.  
  571.                                     /* Are we to display object transfers? */
  572.  
  573.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"TRANSFERS"))
  574.                                     DummyInput[Count++] = "-t";
  575.  
  576.                                     /* Are we to enable the Tandy mode? */
  577.  
  578.                                 if(FindToolType((STRPTR *)Icon -> do_ToolTypes,"TANDY"))
  579.                                     DummyInput[Count++] = "-T";
  580.                             }
  581.  
  582.                                 /* Free the icon data. */
  583.  
  584.                             FreeDiskObject(Icon);
  585.                         }
  586.                     }
  587.                 }
  588.             }
  589.         }
  590.  
  591.             /* Did we get a project file name? */
  592.  
  593.         if(ProjectName[0])
  594.         {
  595.                 /* Supply restore command. */
  596.  
  597.             DummyInput[Count++] = "-r";
  598.  
  599.                 /* Add the name of the file to
  600.                  * be restored.
  601.                  */
  602.  
  603.             if(DummyInput[Count] = (STRPTR)malloc(strlen(ProjectName) + 1))
  604.                 strcpy(DummyInput[Count++],ProjectName);
  605.             else
  606.                 Count--;
  607.         }
  608.  
  609.             /* Have another try opening the system libraries. */
  610.  
  611.         if(ConOpenLibs())
  612.         {
  613.                 /* No custom story file support. */
  614.  
  615.             if(NewOS)
  616.             {
  617.                 char *Buffer;
  618.  
  619.                     /* Did we get a story file name? */
  620.  
  621.                 if(StoryName[0])
  622.                 {
  623.                         /* Is it a valid story file? */
  624.  
  625.                     if(!ConCheckStory(StoryName))
  626.                     {
  627.                             /* Can we locate any story file? */
  628.  
  629.                         if(Buffer = ConLocateStory("",StoryName))
  630.                             strcpy(StoryName,Buffer);
  631.                         else
  632.                         {
  633.                                 /* Prompt the user to select a new one. */
  634.  
  635.                             if(!GameSelect(StoryName))
  636.                                 StoryName[0] = 0;
  637.                         }
  638.                     }
  639.                 }
  640.                 else
  641.                 {
  642.                         /* Can we locate any story file? */
  643.  
  644.                     if(Buffer = ConLocateStory("",""))
  645.                         strcpy(StoryName,Buffer);
  646.                     else
  647.                     {
  648.                             /* Obviously not, so prompt
  649.                              * the user to select a new one.
  650.                              */
  651.  
  652.                         if(!GameSelect(StoryName))
  653.                             StoryName[0] = 0;
  654.                     }
  655.                 }
  656.             }
  657.         }
  658.  
  659.             /* Did we get a story file name? */
  660.  
  661.         if(StoryName[0])
  662.         {
  663.                 /* Add the name of the story
  664.                  * file to be used.
  665.                  */
  666.  
  667.             if(DummyInput[Count] = (STRPTR)malloc(strlen(StoryName) + 1))
  668.                 strcpy(DummyInput[Count++],StoryName);
  669.         }
  670.  
  671.             /* Return new number of arguments. */
  672.  
  673.         return(Count);
  674.     }
  675.     else
  676.         return(argc);
  677. }
  678.  
  679. /*
  680.  * Function:    scr_getopt()
  681.  *
  682.  * Arguments:
  683.  *      c           option found
  684.  *      arg         option argument (if requested)
  685.  *
  686.  * Description:
  687.  *      This function is called whenever a command-line option
  688.  *      specified in scr_opt_list (above) is found on the command
  689.  *      line.
  690.  */
  691.  
  692. void
  693. scr_getopt(int c,const char *arg)
  694. {
  695.         /* Are we to open a custom screen? */
  696.  
  697.     if(c == 'C')
  698.         UseCustomScreen = TRUE;
  699.  
  700.         /* Are we to use a special list font? */
  701.  
  702.     if(c == 'L')
  703.         strcpy(ListFontName,arg);
  704.  
  705.         /* Are we to use a special text font? */
  706.  
  707.     if(c == 'F')
  708.         strcpy(TextFontName,arg);
  709.  
  710.         /* Are we to use a special font size? */
  711.  
  712.     if(c == 'S')
  713.         FontSize = atoi(arg);
  714. }
  715.  
  716. /*
  717.  * Function:    scr_setup()
  718.  *
  719.  * Arguments:
  720.  *      margin      # of spaces in the right margin.
  721.  *      indent      # of spaces in the left margin.
  722.  *      scr_sz      # of lines on the screen.
  723.  *      context     # of lines of context to keep when scrolling
  724.  *
  725.  * Description:
  726.  *      This function should set up generic items in the screen
  727.  *      interface that may need to be done before *any* output is
  728.  *      done.
  729.  *
  730.  *      If SCR_SZ is not 0, then this function must use SCR_SZ as the
  731.  *      number of lines the screen can hold at once, no matter what it
  732.  *      may infer otherwise.  If SCR_SZ is 0, then the function must
  733.  *      figure the size of the screen as best it can.
  734.  *
  735.  * Notes:
  736.  *      Any terminal initialization needed only for actually playing
  737.  *      the game should go in scr_begin(), not here.
  738.  */
  739.  
  740. int
  741. scr_setup(int margin,int indent,int scr_sz,int context)
  742. {
  743.     int Columns = 75;
  744.  
  745.         /* Remember the config data. */
  746.  
  747.     ConLineMargin    = margin;
  748.     ConLineIndent    = indent;
  749.     ConLineContext    = context;
  750.  
  751.         /* Return number of on-screen columns. */
  752.  
  753.     if(!WBenchMsg && SysBase -> LibNode . lib_Version >= 37)
  754.     {
  755.         struct InfoData *InfoData;
  756.  
  757.         if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY))
  758.         {
  759.             if(DoPkt1(ThisProcess -> pr_ConsoleTask,ACTION_DISK_INFO,MKBADDR(InfoData)))
  760.             {
  761.                 struct ConUnit *ConUnit = (struct ConUnit *)((struct IOStdReq *)InfoData -> id_InUse) -> io_Unit;
  762.  
  763.                 Columns = ConUnit -> cu_XMax + 1;
  764.             }
  765.  
  766.             FreeVec(InfoData);
  767.         }
  768.     }
  769.  
  770.         /* Return the number of columns. */
  771.  
  772.     return(Columns);
  773. }
  774.  
  775. /*
  776.  * Function:    scr_shutdown()
  777.  *
  778.  * Description:
  779.  *      This function will be called just before we exit.
  780.  */
  781.  
  782. void
  783. scr_shutdown()
  784. {
  785.     /* Nothing happens here. */
  786. }
  787.  
  788. /*
  789.  * Function:    scr_begin()
  790.  *
  791.  * Arguments:
  792.  *      game    The game datafile we're about to execute.
  793.  *
  794.  * Description:
  795.  *      This function should perform terminal initializations we need
  796.  *      to actually play the game.
  797.  */
  798.  
  799. void
  800. scr_begin()
  801. {
  802.         /* Set up the console or fail. */
  803.  
  804.     if(ConSetup())
  805.     {
  806.         char    *Buffer;
  807.         int     Len = strlen(gflags . filenm);
  808.  
  809.             /* Block GCC signal handling. */
  810.  
  811. #ifdef __GNUC__
  812.  
  813.         sigset_t trapped;
  814.  
  815.         trapped = TRAPPED_SIGNALS;
  816.  
  817.         if(sigprocmask(SIG_BLOCK,&trapped,NULL) != 0)
  818.         {
  819.             ConCleanup();
  820.  
  821.             exit(RETURN_FAIL);
  822.         }
  823.  
  824. #endif    /* __GNUC__ */
  825.  
  826.             /* Determine number of lines on the screen. */
  827.  
  828.         ConNumLines = (Window -> Height - (Window -> BorderTop + Window -> BorderBottom)) / TextFontHeight;
  829.  
  830.             /* Jump to the end of the screen. */
  831.  
  832.         ConSet(0,(ConNumLines - 1) * TextFontHeight,-1);
  833.  
  834.             /* Clear the status line if any. */
  835.  
  836.         if(gflags . pr_status)
  837.             ConPrintStatus("","");
  838.  
  839.             /* Try to get the story name in case we
  840.              * might need it later.
  841.              */
  842.  
  843.         if(NewOS)
  844.         {
  845.                 /* Is this just the bare game file name
  846.                  * without any path part attached?
  847.                  */
  848.  
  849.             if(FilePart((STRPTR)gflags . filenm) == (STRPTR)gflags . filenm)
  850.             {
  851.                     /* Allocate space for full path. */
  852.  
  853.                 if(StoryName = malloc(Len + MAX_FILENAME_LENGTH))
  854.                 {
  855.                         /* Obtain the current directory name. */
  856.  
  857.                     if(GetCurrentDirName(StoryName,Len + MAX_FILENAME_LENGTH))
  858.                     {
  859.                             /* Build the full path name. */
  860.  
  861.                         if(!AddPart(StoryName,(STRPTR)gflags . filenm,Len + MAX_FILENAME_LENGTH))
  862.                             StoryName = "Story.Data";
  863.                     }
  864.                     else
  865.                         StoryName = "Story.Data";
  866.                 }
  867.                 else
  868.                     StoryName = "Story.Data";
  869.             }
  870.             else
  871.             {
  872.                     /* Remember the name. */
  873.  
  874.                 if(StoryName = malloc(Len + 1))
  875.                     strcpy(StoryName,gflags . filenm);
  876.                 else
  877.                     StoryName = "Story.Data";
  878.             }
  879.         }
  880.         else
  881.         {
  882.                 /* Remember the name. */
  883.  
  884.             if(StoryName = malloc(Len + 1))
  885.                 strcpy(StoryName,gflags . filenm);
  886.             else
  887.                 StoryName = "Story.Data";
  888.         }
  889.  
  890.             /* Determine story file serial number and release. */
  891.  
  892.         if(NewOS)
  893.         {
  894.             if(Buffer = ConLocateStory("",StoryName))
  895.                 ConQueryStoryInformation(Buffer);
  896.         }
  897.  
  898.             /* Make a copy of the game name. */
  899.  
  900.         if(SoundName = malloc(Len + AMIGADOS_NAME_LIMIT))
  901.         {
  902.             strcpy(SoundName,gflags . filenm);
  903.  
  904.                 /* Does the sound file name have any
  905.                  * length, i.e. is it a real name?
  906.                  */
  907.  
  908.             if(Len)
  909.             {
  910.                 int i;
  911.  
  912.                     /* Starting from the end of the
  913.                      * file name look for the first
  914.                      * path character.
  915.                      */
  916.  
  917.                 for(i = Len - 1 ; i >= 0 ; i--)
  918.                 {
  919.                         /* Is it a path name seperation
  920.                          * character?
  921.                          */
  922.  
  923.                     if(SoundName[i] == '/' || SoundName[i] == ':')
  924.                     {
  925.                             /* Append the sound directory
  926.                              * name to the string.
  927.                              */
  928.  
  929.                         SoundPath = &SoundName[i + 1];
  930.  
  931.                             /* We're finished. */
  932.  
  933.                         break;
  934.                     }
  935.                 }
  936.             }
  937.  
  938.                 /* If no proper subdirectory name was
  939.                  * to be found, override the entire
  940.                  * string.
  941.                  */
  942.  
  943.             if(!SoundPath)
  944.                 SoundPath = SoundName;
  945.         }
  946.  
  947.             /* Update the menus. */
  948.  
  949.         if(NewOS)
  950.             ConUpdateMenus();
  951.  
  952.             /* Activate the window and bring the screen to the front. */
  953.  
  954.         if(Window)
  955.         {
  956.             ActivateWindow(Window);
  957.  
  958.             ScreenToFront(Window -> WScreen);
  959.         }
  960.  
  961.             /* This interface supports a multiline status window. */
  962.  
  963.         F1_SETB(B_STATUS_WIN);
  964.     }
  965.     else
  966.         exit(RETURN_FAIL);
  967. }
  968.  
  969. /*
  970.  * Function:    scr_end()
  971.  *
  972.  * Description:
  973.  *      This function will be called after the last line is printed
  974.  *      but before we exit, *only* if scr_begin() was called (*not* if
  975.  *      just scr_startup() was called!)
  976.  */
  977.  
  978. void
  979. scr_end()
  980. {
  981.         /* Is the console available? */
  982.  
  983.     if(Window)
  984.     {
  985.             /* Scroll the screen contents up. */
  986.  
  987.         ConScrollUp();
  988.  
  989.             /* Set special colour. */
  990.  
  991.         ConSetColour(COLOUR_SPECIAL);
  992.  
  993.             /* Block the menu strip. */
  994.  
  995.         ConLockMenus();
  996.  
  997.             /* Set the proportional font. */
  998.  
  999.         SetFont(RPort,ThisFont = PropFont);
  1000.  
  1001.             /* Say goodbye... */
  1002.  
  1003.         ConPrintf("Press any key to exit.");
  1004.  
  1005.             /* Turn on the cursor. */
  1006.  
  1007.         ConCursorOn(CURSOR_AVERAGE);
  1008.  
  1009.             /* Wait for key to be pressed. */
  1010.  
  1011.         ConGetChar(TRUE);
  1012.     }
  1013.  
  1014.         /* If the script file is still open (although it shouldn't)
  1015.          * close it.
  1016.          */
  1017.  
  1018.     if(ScriptFile)
  1019.         scr_close_sf(ScriptFileName,ScriptFile,SF_SCRIPT);
  1020.  
  1021.         /* Perform cleanup. */
  1022.  
  1023.     ConCleanup();
  1024.  
  1025.         /* Enable GCC signal handling again. */
  1026.  
  1027. #ifdef __GNUC__
  1028.  
  1029.     {
  1030.         sigset_t trapped;
  1031.  
  1032.         trapped = TRAPPED_SIGNALS;
  1033.  
  1034.         sigprocmask(SIG_UNBLOCK,&trapped,NULL);
  1035.     }
  1036.  
  1037. #endif    /* __GNUC__ */
  1038. }
  1039.  
  1040. /*
  1041.  * Function:    scr_putline()
  1042.  *
  1043.  * Arguments:
  1044.  *      buffer          Line to be printed.
  1045.  *
  1046.  * Description:
  1047.  *      This function is passed a nul-terminated string and it should
  1048.  *      display the string on the terminal.  It will *not* contain a
  1049.  *      newline character.
  1050.  *
  1051.  *      This function should perform whatever wrapping, paging, etc.
  1052.  *      is necessary, print the string, and generate a final linefeed.
  1053.  *
  1054.  *      If the TI supports proportional-width fonts,
  1055.  *      F2_IS_SET(B_FIXED_FONT) should be checked as appropriate.
  1056.  *
  1057.  *      If the TI supports scripting, F2_IS_SET(B_SCRIPTING) should be
  1058.  *      checked as appropriate.
  1059.  */
  1060.  
  1061. void
  1062. scr_putline(const char *buffer)
  1063. {
  1064.     int MaxLen;
  1065.  
  1066.         /* Determine length of text line. */
  1067.  
  1068.     MaxLen = strlen(buffer);
  1069.  
  1070.         /* Check for scripting. */
  1071.  
  1072.     if(F2_IS_SET(B_SCRIPTING))
  1073.     {
  1074.             /* Is this just a blank line? */
  1075.  
  1076.         if(MaxLen)
  1077.             ScriptSplitLine((char *)buffer,MaxLen,FALSE);
  1078.         else
  1079.             ScriptWrite("",0);
  1080.     }
  1081.  
  1082.         /* Is this just a blank line? */
  1083.  
  1084.     if(MaxLen)
  1085.     {
  1086.             /* Are we to change the text rendering font?
  1087.              * The interpreter may want to change between
  1088.              * a fixed and a proportional-spaced font.
  1089.              */
  1090.  
  1091.         if(F2_IS_SET(B_FIXED_FONT))
  1092.         {
  1093.                 /* Use the fixed-width font. */
  1094.  
  1095.             if(ThisFont != FixedFont)
  1096.                 SetFont(RPort,ThisFont = FixedFont);
  1097.         }
  1098.         else
  1099.         {
  1100.                 /* Use the proportional-spaced font. */
  1101.  
  1102.             if(ThisFont != PropFont)
  1103.                 SetFont(RPort,ThisFont = PropFont);
  1104.         }
  1105.  
  1106.             /* Chop the line into pieces and
  1107.              * print it.
  1108.              */
  1109.  
  1110.         ConSplitLine((char *)buffer,MaxLen,FALSE);
  1111.     }
  1112.     else
  1113.         ConPrintLine("",0,0);
  1114. }
  1115.  
  1116. /*
  1117.  * Function:    scr_putscore()
  1118.  *
  1119.  * Description:
  1120.  *      This function prints the ti_location and ti_status strings
  1121.  *      if it can and if status line printing is enabled.
  1122.  */
  1123.  
  1124. void
  1125. scr_putscore()
  1126. {
  1127.         /* Are we to print the status line? */
  1128.  
  1129.     if(gflags . pr_status)
  1130.     {
  1131.         IMPORT char    *ti_location,
  1132.                 *ti_status;
  1133.  
  1134.             /* Print it. */
  1135.  
  1136.         if(ti_location && ti_status)
  1137.             ConPrintStatus(ti_location,ti_status);
  1138.     }
  1139. }
  1140.  
  1141. /*
  1142.  * Function:    scr_putsound()
  1143.  *
  1144.  * Arguments:
  1145.  *      number      sound number to play
  1146.  *      action      action to perform
  1147.  *      volume      volume to play sound at
  1148.  *      argc        number of valid arguments
  1149.  *
  1150.  * Description:
  1151.  *      This function plays the sound specified if it can; if not it
  1152.  *      prints a line to that effect.
  1153.  *
  1154.  *      If the `argc' value is 1, then the we play `number' of beeps
  1155.  *      (usually the ^G character).
  1156.  *
  1157.  *      If `argc' >1, the `action' argument is used as follows:
  1158.  *
  1159.  *          2:  play sound file
  1160.  *          3:  stop playing sound file
  1161.  *          4:  free sound resources
  1162.  *
  1163.  *      If `argc' >2, the `volume' argument is between 1 and 8 and is
  1164.  *      a volume to play the sound at.
  1165.  */
  1166.  
  1167. void
  1168. scr_putsound(int number,int action,int volume,int argc)
  1169. {
  1170.         /* Single argument? Just beep. */
  1171.  
  1172.     if(argc == 1)
  1173.     {
  1174.             /* Run down the number of beeps to produce. */
  1175.  
  1176.         while(number--)
  1177.         {
  1178.                 /* Beep! */
  1179.  
  1180.             DisplayBeep(Window -> WScreen);
  1181.  
  1182.                 /* Wait a bit. */
  1183.  
  1184.             if(number)
  1185.                 Delay(TICKS_PER_SECOND / 2);
  1186.         }
  1187.     }
  1188.     else
  1189.     {
  1190.             /* Is the sound name buffer available? */
  1191.  
  1192.         if(SoundName)
  1193.         {
  1194.             Bool GotSound;
  1195.  
  1196.                 /* What are we to do next? */
  1197.  
  1198.             switch(action)
  1199.             {
  1200.                     /* If a new sound is to be replayed, stop
  1201.                      * the current sound.
  1202.                      */
  1203.  
  1204.                 case 2:    if(number != SoundNumber && SoundNumber != -1 && SoundControlRequest)
  1205.                     {
  1206.                         SoundAbort();
  1207.  
  1208.                             /* Free previously allocated sound data. */
  1209.  
  1210.                         if(SoundData && SoundLength)
  1211.                         {
  1212.                                 /* Free it. */
  1213.  
  1214.                             FreeMem(SoundData,SoundLength);
  1215.  
  1216.                                 /* Leave no traces. */
  1217.  
  1218.                             SoundData    = NULL;
  1219.                             SoundLength    = 0;
  1220.                         }
  1221.  
  1222.                         SoundNumber = -1;
  1223.                     }
  1224.  
  1225.                         /* Make sure that we have the resources we need,
  1226.                          * either allocate them or rely on the fact that
  1227.                          * the previous call to this routine had already
  1228.                          * triggered the allocation.
  1229.                          */
  1230.  
  1231.                     if(!SoundControlRequest)
  1232.                         GotSound = SoundInit();
  1233.                     else
  1234.                         GotSound = TRUE;
  1235.  
  1236.                         /* Do we have the resources or not? */
  1237.  
  1238.                     if(GotSound)
  1239.                     {
  1240.                             /* If we are to replay the same sound as we
  1241.                              * did before, we are probably to change the
  1242.                              * replay volume.
  1243.                              */
  1244.  
  1245.                         if(SoundNumber == number && SoundNumber != -1)
  1246.                         {
  1247.                                 /* Is the sound still playing? If so,
  1248.                                  * change the volume, else restart
  1249.                                  * it with the new volume.
  1250.                                  */
  1251.  
  1252.                             if(!CheckIO((struct IORequest *)SoundRequestLeft))
  1253.                             {
  1254.                                     /* Set up new volume. */
  1255.  
  1256.                                 SoundControlRequest -> ioa_Request . io_Command    = ADCMD_PERVOL;
  1257.                                 SoundControlRequest -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  1258.                                 SoundControlRequest -> ioa_Volume        = volume * 8;
  1259.  
  1260.                                     /* Tell the device to make the change. */
  1261.  
  1262.                                 SendIO((struct IORequest *)SoundControlRequest);
  1263.                                 WaitIO((struct IORequest *)SoundControlRequest);
  1264.                             }
  1265.                             else
  1266.                             {
  1267.                                     /* Wait for requests to return. */
  1268.  
  1269.                                 SoundAbort();
  1270.  
  1271.                                     /* Set up new volume. */
  1272.  
  1273.                                 SoundRequestLeft  -> ioa_Volume = volume * 8;
  1274.                                 SoundRequestRight -> ioa_Volume = volume * 8;
  1275.  
  1276.                                     /* Stop the sound. */
  1277.  
  1278.                                 SoundStop();
  1279.  
  1280.                                     /* Queue the sound. */
  1281.  
  1282.                                 BeginIO((struct IORequest *)SoundRequestLeft);
  1283.                                 BeginIO((struct IORequest *)SoundRequestRight);
  1284.  
  1285.                                     /* Start the sound. */
  1286.  
  1287.                                 SoundStart();
  1288.                             }
  1289.                         }
  1290.                         else
  1291.                         {
  1292.                                 /* The sound file header. */
  1293.  
  1294.                             struct
  1295.                             {
  1296.                                 UBYTE    Reserved1[2];
  1297.                                 BYTE    Times;        /* How many times to play (0 = continuously). */
  1298.                                 UBYTE    Rate[2];    /* Replay rate (note: little endian). */
  1299.                                 UBYTE    Reserved2[3];
  1300.                                 UWORD    PlayLength;    /* Length of sound to replay. */
  1301.                             } SoundHeader;
  1302.  
  1303.                                 /* Sound file handle and name buffer. */
  1304.  
  1305.                             FILE *SoundFile;
  1306.  
  1307.                                 /* Cancel the number of the previously loaded
  1308.                                  * sound in case the load fails.
  1309.                                  */
  1310.  
  1311.                             SoundNumber = -1;
  1312.  
  1313.                                 /* Set up the sound file name. */
  1314.  
  1315.                             sprintf(SoundPath,"sound/s%d.dat",number);
  1316.  
  1317.                                 /* Open the file for reading. */
  1318.  
  1319.                             if(SoundFile = fopen(SoundName,"rb"))
  1320.                             {
  1321.                                     /* Read the file header. */
  1322.  
  1323.                                 if(fread(&SoundHeader,sizeof(SoundHeader),1,SoundFile) == 1)
  1324.                                 {
  1325.                                         /* Remember the sound file length. */
  1326.  
  1327.                                     SoundLength = SoundHeader . PlayLength;
  1328.  
  1329.                                         /* Allocate chip ram for the sound data. */
  1330.  
  1331.                                     if(SoundData = (APTR)AllocMem(SoundLength,MEMF_CHIP))
  1332.                                     {
  1333.                                             /* Read the sound data. */
  1334.  
  1335.                                         if(fread(SoundData,SoundLength,1,SoundFile) == 1)
  1336.                                         {
  1337.                                                 /* Turn the replay rate into a
  1338.                                                  * sensible number.
  1339.                                                  */
  1340.  
  1341.                                             ULONG Rate = (GfxBase -> DisplayFlags & PAL ? 3546895 : 3579545) / ((((UWORD)SoundHeader . Rate[1]) << 8) | SoundHeader . Rate[0]);
  1342.  
  1343.                                                 /* Set up the left channel. */
  1344.  
  1345.                                             SoundRequestLeft -> ioa_Request . io_Command    = CMD_WRITE;
  1346.                                             SoundRequestLeft -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  1347.                                             SoundRequestLeft -> ioa_Period            = Rate;
  1348.                                             SoundRequestLeft -> ioa_Volume            = volume * 8;
  1349.                                             SoundRequestLeft -> ioa_Cycles            = SoundHeader . Times;
  1350.                                             SoundRequestLeft -> ioa_Data            = SoundData;
  1351.                                             SoundRequestLeft -> ioa_Length            = SoundLength;
  1352.  
  1353.                                                 /* Set up the right channel. */
  1354.  
  1355.                                             SoundRequestRight -> ioa_Request . io_Command    = CMD_WRITE;
  1356.                                             SoundRequestRight -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  1357.                                             SoundRequestRight -> ioa_Period            = Rate;
  1358.                                             SoundRequestRight -> ioa_Volume            = volume * 8;
  1359.                                             SoundRequestRight -> ioa_Cycles            = SoundHeader . Times;
  1360.                                             SoundRequestRight -> ioa_Data            = SoundData;
  1361.                                             SoundRequestRight -> ioa_Length            = SoundLength;
  1362.  
  1363.                                                 /* Set up the control request. */
  1364.  
  1365.                                             SoundControlRequest -> ioa_Period        = Rate;
  1366.  
  1367.                                                 /* Stop playing any sound. */
  1368.  
  1369.                                             SoundStop();
  1370.  
  1371.                                                 /* Queue the sound. */
  1372.  
  1373.                                             BeginIO((struct IORequest *)SoundRequestLeft);
  1374.                                             BeginIO((struct IORequest *)SoundRequestRight);
  1375.  
  1376.                                                 /* Play the sound. */
  1377.  
  1378.                                             SoundStart();
  1379.  
  1380.                                                 /* Remember the number of the current sound. */
  1381.  
  1382.                                             SoundNumber = number;
  1383.                                         }
  1384.                                         else
  1385.                                         {
  1386.                                                 /* The load failed, free the audio memory. */
  1387.  
  1388.                                             FreeMem(SoundData,SoundLength);
  1389.  
  1390.                                                 /* Leave no traces. */
  1391.  
  1392.                                             SoundData    = NULL;
  1393.                                             SoundLength    = 0;
  1394.                                         }
  1395.                                     }
  1396.                                 }
  1397.  
  1398.                                     /* Close the sound file. */
  1399.  
  1400.                                 fclose(SoundFile);
  1401.                             }
  1402.                         }
  1403.                     }
  1404.  
  1405.                     break;
  1406.  
  1407.                     /* Stop the current sound. */
  1408.  
  1409.                 case 3:    SoundExit();
  1410.                     break;
  1411.             }
  1412.         }
  1413.     }
  1414. }
  1415.  
  1416. /*
  1417.  * Function:    scr_putmesg()
  1418.  *
  1419.  * Arguments:
  1420.  *      buffer      message string to be printed.
  1421.  *      is_err      1 if message is an error message, 0 if it's not.
  1422.  *
  1423.  * Description:
  1424.  *      This function prints out a message from the interpreter, not
  1425.  *      from the game itself.  Often these are errors (IS_ERROR==1)
  1426.  *      but not necessarily.
  1427.  */
  1428.  
  1429. void
  1430. scr_putmesg(const char *buffer,Bool is_err)
  1431. {
  1432.         /* Provide an empty line. */
  1433.  
  1434.     ConScrollUp();
  1435.  
  1436.         /* Is this supposed to be an error message? */
  1437.  
  1438.     if(is_err)
  1439.     {
  1440.             /* Set error text colour. */
  1441.  
  1442.         ConSetColour(COLOUR_ERROR);
  1443.  
  1444.             /* Display the error message. */
  1445.  
  1446.         ConPrintf("[%s]",buffer);
  1447.  
  1448.             /* Reset text colour. */
  1449.  
  1450.         ConSetColour(COLOUR_TEXT);
  1451.     }
  1452.     else
  1453.         ConPrintf("[%s]",buffer);
  1454. }
  1455.  
  1456. /*
  1457.  * Function:    scr_getline()
  1458.  *
  1459.  * Arguments:
  1460.  *      prompt    - prompt to be printed
  1461.  *      length    - total size of BUFFER
  1462.  *      buffer    - buffer to return nul-terminated response in
  1463.  *
  1464.  * Returns:
  1465.  *      # of chars stored in BUFFER
  1466.  *
  1467.  * Description:
  1468.  *      Reads a line of input and returns it.  Handles all "special
  1469.  *      operations" such as readline history support, shell escapes,
  1470.  *      etc. invisibly to the caller.  Note that the returned BUFFER
  1471.  *      will be at most LENGTH-1 chars long because the last char will
  1472.  *      always be the nul character.
  1473.  *
  1474.  *      If the command begins with ESC_CHAR then it's an interpreter
  1475.  *      escape command; call ti_escape() with the rest of the line,
  1476.  *      then ask for another command.
  1477.  *
  1478.  * Notes:
  1479.  *      May print the STATUS buffer more than once if necessary (i.e.,
  1480.  *      a shell escape messed up the screen, a history listing was
  1481.  *      generated, etc.).
  1482.  */
  1483.  
  1484. int
  1485. scr_getline(const char *prompt,int length,char *buffer)
  1486. {
  1487.     char    *EscapeChar    = ESC_CHAR,
  1488.         *NewPrompt    = (char *)prompt;
  1489.     Bool     Done        = FALSE;
  1490.     int     InputLength;
  1491.  
  1492.         /* Loop until user provides any input. */
  1493.  
  1494.     do
  1495.     {
  1496.             /* Get the scripting menu item. */
  1497.  
  1498.         if(NewOS)
  1499.         {
  1500.             struct MenuItem *Item;
  1501.  
  1502.             if(Item = ItemAddress(Menu,FULLMENUNUM(MENU_PROJECT,PROJECTMENU_SCRIPT,NOSUB)))
  1503.             {
  1504.                     /* Change the state of the checkmark. */
  1505.  
  1506.                 if(!F2_IS_SET(B_SCRIPTING) && (Item -> Flags & CHECKED))
  1507.                     Item -> Flags &= ~CHECKED;
  1508.             }
  1509.  
  1510.                 /* Update the menu strip. */
  1511.  
  1512.             ConUpdateMenus();
  1513.         }
  1514.  
  1515.             /* Print the status line. */
  1516.  
  1517.         scr_putscore();
  1518.  
  1519.             /* Scroll the screen contents up. */
  1520.  
  1521.         ConScrollUp();
  1522.  
  1523.             /* Do we have any prompt to print? */
  1524.  
  1525.         if(NewPrompt[0])
  1526.         {
  1527.                 /* Split the prompt and print it. */
  1528.  
  1529.             NewPrompt = ConSplitLine(NewPrompt,strlen(NewPrompt),TRUE);
  1530.  
  1531.                 /* If the prompt was turned into several
  1532.                  * lines of text, scroll the screen
  1533.                  * contents up.
  1534.                  */
  1535.  
  1536.             if(NewPrompt != prompt)
  1537.                 ConScrollUp();
  1538.  
  1539.                 /* Is there still anything left of it?
  1540.                  * If so, print it.
  1541.                  */
  1542.  
  1543.             if(NewPrompt[0])
  1544.                 ConWrite(NewPrompt,-1,0);
  1545.         }
  1546.  
  1547.             /* Enough done. */
  1548.  
  1549.         ConLinesPrinted = 0;
  1550.  
  1551.             /* Turn on the cursor. */
  1552.  
  1553.         ConCursorOn(CURSOR_AVERAGE);
  1554.  
  1555.             /* Change the text colour. */
  1556.  
  1557.         ConSetColour(COLOUR_INPUT);
  1558.  
  1559.             /* Read the line of text. */
  1560.  
  1561.         InputLength = ConInput(NewPrompt,buffer,length,TRUE);
  1562.  
  1563.             /* Strip trailing blank spaces. */
  1564.  
  1565.         while(InputLength > 0)
  1566.         {
  1567.             if(buffer[InputLength - 1] == ' ')
  1568.                 InputLength--;
  1569.             else
  1570.                 break;
  1571.         }
  1572.  
  1573.             /* Provide null-termination. */
  1574.  
  1575.         buffer[InputLength] = 0;
  1576.  
  1577.             /* Set the text colour. */
  1578.  
  1579.         ConSetColour(COLOUR_TEXT);
  1580.  
  1581.             /* Turn the cursor off. */
  1582.  
  1583.         ConCursorOff();
  1584.  
  1585.             /* Special actions to be taken? */
  1586.  
  1587.         if(*buffer == *EscapeChar)
  1588.         {
  1589.                 /* Perform special actions. */
  1590.  
  1591.             ti_escape(&buffer[1]);
  1592.  
  1593.                 /* Update options menu items. */
  1594.  
  1595.             if(NewOS)
  1596.                 ConUpdateMenus();
  1597.         }
  1598.         else
  1599.             Done = TRUE;
  1600.     }
  1601.     while(!Done);
  1602.  
  1603.         /* Output text to script file. */
  1604.  
  1605.     if(F2_IS_SET(B_SCRIPTING))
  1606.     {
  1607.             /* Split the prompt. */
  1608.  
  1609.         NewPrompt = ScriptSplitLine((char *)prompt,strlen(prompt),TRUE);
  1610.  
  1611.             /* Build prompt and input string. */
  1612.  
  1613.         strcpy(TempBuffer,NewPrompt);
  1614.         strcat(TempBuffer,buffer);
  1615.  
  1616.             /* Transcribe it. */
  1617.  
  1618.         ScriptWrite(TempBuffer,strlen(TempBuffer));
  1619.     }
  1620.  
  1621.         /* Return number of characters read. */
  1622.  
  1623.     return(InputLength);
  1624. }
  1625.  
  1626. /*
  1627.  * Function:    scr_window()
  1628.  *
  1629.  * Arguments:
  1630.  *      size      - 0 to delete, non-0 means create with SIZE.
  1631.  *
  1632.  * Description:
  1633.  *      Causes a status window to be created if supported by the
  1634.  *      terminal interface; note this function won't be called unless
  1635.  *      F1_SETB(B_STATUS_WIN) is invoked in scr_begin().
  1636.  *
  1637.  * Notes:
  1638.  */
  1639.  
  1640. void
  1641. scr_window(int size)
  1642. {
  1643.         /* Are we to set up the status window? */
  1644.  
  1645.     if(size)
  1646.     {
  1647.             /* Determine new status window area. */
  1648.  
  1649.         ConNumStatusLines = size + 1;
  1650.  
  1651.             /* Clear the status window area. */
  1652.  
  1653.         SetAPen(RPort,ConBackPen);
  1654.  
  1655.         RectFill(RPort,Window -> BorderLeft,Window -> BorderTop + TextFontHeight,Window -> Width - Window -> BorderRight - 1,Window -> BorderTop + TextFontHeight * (size + 1) - 1);
  1656.  
  1657.         SetAPen(RPort,ConTextPen);
  1658.     }
  1659.     else
  1660.     {
  1661.             /* Reset to defaults. */
  1662.  
  1663.         ConNumStatusLines    = 1;
  1664.         ConOutputWindow        = 0;
  1665.     }
  1666. }
  1667.  
  1668. /*
  1669.  * Function:    scr_set_win()
  1670.  *
  1671.  * Arguments:
  1672.  *      win       - 0==select text window, 1==select status window
  1673.  *
  1674.  * Description:
  1675.  *      Selects a different window.  This function won't be called
  1676.  *      unless call F1_SETB(B_STATUS_WIN) in scr_begin().
  1677.  *
  1678.  * Notes:
  1679.  */
  1680.  
  1681. void
  1682. scr_set_win(int win)
  1683. {
  1684.     STATIC LONG    SavedCursorX,
  1685.             SavedCursorY;
  1686.  
  1687.         /* Are we to select the status window? */
  1688.  
  1689.     if(win)
  1690.     {
  1691.             /* Is the text window still active? */
  1692.  
  1693.         if(!ConOutputWindow)
  1694.         {
  1695.                 /* Remember old cursor position. */
  1696.  
  1697.             SavedCursorX = CursorX;
  1698.             SavedCursorY = CursorY;
  1699.  
  1700.                 /* Turn the cursor off, we
  1701.                  * won't be needing it.
  1702.                  */
  1703.  
  1704.             ConCursorOff();
  1705.  
  1706.                 /* Remember new output window area. */
  1707.  
  1708.             ConOutputWindow = win;
  1709.         }
  1710.  
  1711.             /* Move to the beginning of the status window. */
  1712.  
  1713.         CursorY = TextFontHeight;
  1714.         CursorX = 0;
  1715.     }
  1716.     else
  1717.     {
  1718.             /* Is the status window still active? */
  1719.  
  1720.         if(ConOutputWindow)
  1721.         {
  1722.                 /* Get back the old cursor position. */
  1723.  
  1724.             CursorX = SavedCursorX;
  1725.             CursorY = SavedCursorY;
  1726.  
  1727.                 /* Turn the cursor back on. */
  1728.  
  1729.             ConCursorOn(CURSOR_NOCHANGE);
  1730.  
  1731.                 /* Change the current output window. */
  1732.  
  1733.             ConOutputWindow = win;
  1734.         }
  1735.     }
  1736. }
  1737.  
  1738. /*
  1739.  * Function:    scr_open_sf()
  1740.  *
  1741.  * Arguments:
  1742.  *      length    - total size of BUFFER
  1743.  *      buffer    - buffer to return nul-terminated filename in
  1744.  *      type      - SF_SAVE     opening the file to save into
  1745.  *                  SF_RESTORE  opening the file to restore from
  1746.  *                  SF_SCRIPT   opening a file for scripting
  1747.  *
  1748.  * Returns:
  1749.  *      FILE* - reference to the opened file, or
  1750.  *      NULL  - errno==0: operation cancelled, else error opening file
  1751.  *
  1752.  * Description:
  1753.  *      Obtains the name of the file to be opened for writing (if
  1754.  *      TYPE==SF_SAVE or SF_SCRIPT) or reading (if TYPE==SF_RESTORE),
  1755.  *      opens the file with fopen(), and returns the FILE*.
  1756.  *
  1757.  *      The name of the file should be stored in BUFFER.  Upon initial
  1758.  *      calling BUFFER contains a possible default filename.
  1759.  *
  1760.  *      if LENGTH==0 then don't ask the user for a name, just use
  1761.  *      BUFFER.  This means, for example, we got the -r option to
  1762.  *      restore the file.
  1763.  *
  1764.  *      If the fopen() fails just return NULL: if errno!=0 then an
  1765.  *      error will be printed.
  1766.  *
  1767.  * Notes:
  1768.  *      History is turned off here (why would anyone want it?)
  1769.  */
  1770.  
  1771. FILE *
  1772. scr_open_sf(int length, char *buffer, int type)
  1773. {
  1774.         /* Prompt buffer and filename buffer. */
  1775.  
  1776.     STATIC char    FileName[MAX_FILENAME_LENGTH],
  1777.             Prompt[MAX_FILENAME_LENGTH + 18];
  1778.  
  1779.         /* Are we running under control of Kickstart 2.04 or higher? */
  1780.  
  1781.     if(NewOS)
  1782.     {
  1783.         Bool     GotName = FALSE,
  1784.              GotFile = FALSE;
  1785.         int     Len;
  1786.         char    *ScriptMode;
  1787.  
  1788.             /* Are we to prompt for a file name? */
  1789.  
  1790.         if(length)
  1791.         {
  1792.             STATIC struct Requester BlockRequester;
  1793.  
  1794.                 /* Clear the window requester. */
  1795.  
  1796.             memset(&BlockRequester,0,sizeof(struct Requester));
  1797.  
  1798.                 /* Install the requester, blocking all window input. */
  1799.  
  1800.             Request(&BlockRequester,Window);
  1801.  
  1802.                 /* Set the window wait pointer. */
  1803.  
  1804.             WaitPointer(Window);
  1805.  
  1806.                 /* No scripting in this part, please. */
  1807.  
  1808.             if(type != SF_SCRIPT)
  1809.             {
  1810.                     /* Are we to load a saved game file? */
  1811.  
  1812.                 if(ProjectName[0])
  1813.                 {
  1814.                         /* Is the project name small enough to fit? */
  1815.  
  1816.                     if((Len = strlen(ProjectName)) < length)
  1817.                     {
  1818.                             /* Store the project name. */
  1819.  
  1820.                         strcpy(buffer,ProjectName);
  1821.  
  1822.                             /* Now we've got a name. */
  1823.  
  1824.                         GotName = TRUE;
  1825.                     }
  1826.  
  1827.                         /* Clear the project name. */
  1828.  
  1829.                     ProjectName[0] = 0;
  1830.                 }
  1831.                 else
  1832.                 {
  1833.                     char *Index;
  1834.  
  1835.                         /* Loop until a proper name is entered or the
  1836.                          * selection is aborted.
  1837.                          */
  1838.  
  1839.                     do
  1840.                     {
  1841.                             /* Save the input file name. */
  1842.  
  1843.                         strcpy(FileName,buffer);
  1844.  
  1845.                             /* Extract the path name. */
  1846.  
  1847.                         if(Index = PathPart(FileName))
  1848.                             *Index = 0;
  1849.  
  1850.                             /* If no path name is given, supply the
  1851.                              * current directory.
  1852.                              */
  1853.  
  1854.                         if(!FileName[0])
  1855.                         {
  1856.                             /* Try to obtain the current directory name.
  1857.                              * If this fails, leave the path name empty.
  1858.                              */
  1859.  
  1860.                             if(!GetCurrentDirName(FileName,MAX_FILENAME_LENGTH))
  1861.                                 FileName[0] = 0;
  1862.                         }
  1863.  
  1864.                             /* Request a file and path name. */
  1865.  
  1866.                         if(AslRequestTags(GameFileRequest,
  1867.                             ASL_Window,    Window,
  1868.                             ASL_Dir,    FileName,
  1869.                             ASL_File,    FilePart(buffer),
  1870.                             ASL_FuncFlags,    (type == SF_SAVE) ? FILF_SAVE | FILF_PATGAD    : FILF_PATGAD,
  1871.                             ASL_Hail,    (type == SF_SAVE) ? "Select game file to save"    : "Select game file to restore",
  1872.                             ASL_Pattern,    "#?.Save",
  1873.                         TAG_DONE))
  1874.                         {
  1875.                                 /* Did the user select a file? */
  1876.  
  1877.                             if(Len = strlen((char *)GameFileRequest -> rf_File))
  1878.                             {
  1879.                                 char *Name = (char *)GameFileRequest -> rf_File;
  1880.  
  1881.                                     /* Are we to save a game file? */
  1882.  
  1883.                                 if(type == SF_SAVE)
  1884.                                 {
  1885.                                     Bool NewName = FALSE;
  1886.  
  1887.                                         /* Is there enough space left to append
  1888.                                          * the `.Save' suffix?
  1889.                                          */
  1890.  
  1891.                                     if(Len <= AMIGADOS_NAME_LIMIT - SAVE_SUFFIX_LENGTH)
  1892.                                     {
  1893.                                         if(Len > SAVE_SUFFIX_LENGTH)
  1894.                                         {
  1895.                                                 /* Does it already have the `.Save' suffix
  1896.                                                  * attached?
  1897.                                                  */
  1898.  
  1899.                                             if(Stricmp((STRPTR)&Name[Len - SAVE_SUFFIX_LENGTH],SAVE_SUFFIX))
  1900.                                                 NewName = TRUE;
  1901.                                         }
  1902.                                         else
  1903.                                             NewName = TRUE;
  1904.                                     }
  1905.  
  1906.                                         /* Are we to append the `.Save' suffix? */
  1907.  
  1908.                                     if(NewName)
  1909.                                     {
  1910.                                             /* Tack on the suffix. */
  1911.  
  1912.                                         strcpy(TempBuffer,Name);
  1913.                                         strcat(TempBuffer,SAVE_SUFFIX);
  1914.  
  1915.                                         Name = TempBuffer;
  1916.                                     }
  1917.                                 }
  1918.  
  1919.                                     /* Copy the path name. */
  1920.  
  1921.                                 strcpy(FileName,(char *)GameFileRequest -> rf_Dir);
  1922.  
  1923.                                     /* Attach the file name. */
  1924.  
  1925.                                 if(AddPart((STRPTR)FileName,(STRPTR)Name,MAX_FILENAME_LENGTH))
  1926.                                 {
  1927.                                         /* Copy the new file name. */
  1928.  
  1929.                                     strcpy(buffer,FileName);
  1930.  
  1931.                                         /* Check whether the destination file already
  1932.                                          * exists.
  1933.                                          */
  1934.  
  1935.                                     if(type == SF_SAVE)
  1936.                                     {
  1937.                                         BPTR FileLock;
  1938.  
  1939.                                             /* Does it already exist? */
  1940.  
  1941.                                         if(FileLock = Lock(FileName,ACCESS_READ))
  1942.                                         {
  1943.                                                 /* Release the lock. */
  1944.  
  1945.                                             UnLock(FileLock);
  1946.  
  1947.                                                 /* Ask the user what to do next. */
  1948.  
  1949.                                             switch(ConShowRequest(Window,"You are about to overwrite an existing file!","Proceed|New name|Cancel"))
  1950.                                             {
  1951.                                                 case SAVE_CANCEL:    GotFile = TRUE;
  1952.                                                             break;
  1953.  
  1954.                                                 case SAVE_PROCEED:    GotFile = GotName = TRUE;
  1955.                                                             break;
  1956.  
  1957.                                                 case SAVE_NEWNAME:    GotFile = FALSE;
  1958.                                                             break;
  1959.                                             }
  1960.                                         }
  1961.                                         else
  1962.                                         {
  1963.                                                 /* Remember that we got a new file name. */
  1964.  
  1965.                                             GotFile = GotName = TRUE;
  1966.                                         }
  1967.                                     }
  1968.                                     else
  1969.                                     {
  1970.                                             /* Remember that we got a new file name. */
  1971.  
  1972.                                         GotFile = GotName = TRUE;
  1973.                                     }
  1974.                                 }
  1975.                                 else
  1976.                                     GotFile = TRUE;
  1977.                             }
  1978.                             else
  1979.                                 GotFile = TRUE;
  1980.                         }
  1981.                         else
  1982.                             GotFile = TRUE;
  1983.                     }
  1984.                     while(!GotFile);
  1985.                 }
  1986.             }
  1987.             else
  1988.             {
  1989.                     /* If no printer width has been defined yet,
  1990.                      * consult the system preferences settings.
  1991.                      */
  1992.  
  1993.                 if(!ScriptWidth)
  1994.                 {
  1995.                     struct Preferences Prefs;
  1996.  
  1997.                         /* Get the system preferences. */
  1998.  
  1999.                     if(GetPrefs(&Prefs,sizeof(struct Preferences)))
  2000.                     {
  2001.                             /* Adjust the width if too small. */
  2002.  
  2003.                         if((ScriptWidth = (int)Prefs . PrintRightMargin - (int)Prefs . PrintLeftMargin + 1) < MIN_PRINTER_COLUMNS)
  2004.                             ScriptWidth = MIN_PRINTER_COLUMNS;
  2005.                     }
  2006.                 }
  2007.  
  2008.                     /* Loop until we get a name. */
  2009.  
  2010.                 do
  2011.                 {
  2012.                         /* Get the desired output file and width. */
  2013.  
  2014.                     if(ScriptGetPrinterName((STRPTR)buffer,&ScriptWidth))
  2015.                     {
  2016.                         STRPTR Index;
  2017.  
  2018.                             /* Get the file path part. */
  2019.  
  2020.                         Index = PathPart(buffer);
  2021.  
  2022.                             /* Is it a real file or a device
  2023.                              * name such as "PRT:"?
  2024.                              */
  2025.  
  2026.                         if(*Index)
  2027.                         {
  2028.                             BPTR FileLock;
  2029.  
  2030.                                 /* Does it exist already? */
  2031.  
  2032.                             if(FileLock = Lock(buffer,ACCESS_READ))
  2033.                             {
  2034.                                     /* Release the lock. */
  2035.  
  2036.                                 UnLock(FileLock);
  2037.  
  2038.                                     /* Ask the user what to do next. */
  2039.  
  2040.                                 switch(ConShowRequest(Window,"You are about to overwrite an existing file!","Proceed|Append|New name|Cancel"))
  2041.                                 {
  2042.                                     case SCRIPT_CANCEL:    GotFile = TRUE;
  2043.  
  2044.                                                 break;
  2045.  
  2046.                                     case SCRIPT_PROCEED:    ScriptMode = "w";
  2047.  
  2048.                                                 GotFile = GotName = TRUE;
  2049.  
  2050.                                                 break;
  2051.  
  2052.                                     case SCRIPT_APPEND:    ScriptMode = "a";
  2053.  
  2054.                                                 GotFile = GotName = TRUE;
  2055.  
  2056.                                                 break;
  2057.  
  2058.                                     case SCRIPT_NEWNAME:    continue;
  2059.                                 }
  2060.                             }
  2061.                             else
  2062.                             {
  2063.                                 ScriptMode = "w";
  2064.  
  2065.                                 GotFile = GotName = TRUE;
  2066.                             }
  2067.                         }
  2068.                         else
  2069.                         {
  2070.                             ScriptMode = "w";
  2071.  
  2072.                             GotFile = GotName = TRUE;
  2073.                         }
  2074.                     }
  2075.                     else
  2076.                         GotFile = TRUE;
  2077.                 }
  2078.                 while(!GotFile);
  2079.             }
  2080.  
  2081.                 /* Remove the window wait pointer. */
  2082.  
  2083.             ClearPointer(Window);
  2084.  
  2085.                 /* Remove the blocking requester. */
  2086.  
  2087.             EndRequest(&BlockRequester,Window);
  2088.         }
  2089.         else
  2090.             GotName = TRUE;
  2091.  
  2092.             /* Return the result. */
  2093.  
  2094.         if(GotName)
  2095.             {
  2096.             FILE *File;
  2097.  
  2098.                 /* Get the file name. */
  2099.  
  2100.             strcpy(WindowTitle,FilePart((STRPTR)buffer));
  2101.  
  2102.                 /* Determine file name length. */
  2103.  
  2104.             Len = strlen(WindowTitle);
  2105.  
  2106.                 /* Is it long enough to hold the ".Save" suffix? */
  2107.  
  2108.             if(Len > SAVE_SUFFIX_LENGTH)
  2109.             {
  2110.                     /* Is the ".Save" suffix present? If so,
  2111.                      * get rid of it.
  2112.                      */
  2113.  
  2114.                 if(!Stricmp(&WindowTitle[Len - SAVE_SUFFIX_LENGTH],SAVE_SUFFIX))
  2115.                     WindowTitle[Len - SAVE_SUFFIX_LENGTH] = 0;
  2116.             }
  2117.  
  2118.                 /* Open the output file. */
  2119.  
  2120.             switch(type)
  2121.             {
  2122.                     /* Saved game file handling. */
  2123.  
  2124.                 case SF_SAVE:        if(File = fopen(buffer,"wb"))
  2125.                             {
  2126.                                 if(!Screen)
  2127.                                     SetWindowTitles(Window,WindowTitle,(STRPTR)~0);
  2128.                             }
  2129.  
  2130.                             return(File);
  2131.  
  2132.                 case SF_RESTORE:    if(File = fopen(buffer,"rb"))
  2133.                             {
  2134.                                 if(!Screen)
  2135.                                     SetWindowTitles(Window,WindowTitle,(STRPTR)~0);
  2136.                             }
  2137.  
  2138.                             return(File);
  2139.  
  2140.                     /* Script file handling. */
  2141.  
  2142.                 case SF_SCRIPT:        if(ScriptFile = fopen(buffer,ScriptMode))
  2143.                             {
  2144.                                 struct MenuItem *Item;
  2145.  
  2146.                                 strcpy(ScriptFileName,buffer);
  2147.  
  2148.                                     /* Block the menu strip. */
  2149.  
  2150.                                 ConLockMenus();
  2151.  
  2152.                                     /* Change the `Script...' menu item
  2153.                                      * according to the current scripting
  2154.                                      * settings.
  2155.                                      */
  2156.  
  2157.                                 Item = ItemAddress(Menu,FULLMENUNUM(MENU_PROJECT,PROJECTMENU_SCRIPT,NOSUB));
  2158.  
  2159.                                 Item -> Flags |= CHECKED;
  2160.  
  2161.                                     /* Enable the menu strip again. */
  2162.  
  2163.                                 ConUnlockMenus();
  2164.  
  2165.                                     /* Clear the flag. */
  2166.  
  2167.                                 ScriptAborted = FALSE;
  2168.                             }
  2169.  
  2170.                             return(ScriptFile);
  2171.             }
  2172.         }
  2173.     }
  2174.     else
  2175.     {
  2176.             /* Are we to ask the user to provide any input? */
  2177.  
  2178.         if(length)
  2179.         {
  2180.                 /* Tell the user what to do. */
  2181.  
  2182.             scr_putline("Enter a file name.");
  2183.  
  2184.                 /* Build a prompt string. */
  2185.  
  2186.             sprintf(Prompt,"(Default is \"%s\") >",buffer);
  2187.  
  2188.                 /* Read the input line. */
  2189.  
  2190.             if(!scr_getline(Prompt,MAX_FILENAME_LENGTH,FileName))
  2191.                 strcpy(FileName,buffer);
  2192.  
  2193.                 /* Are we to open a file for saving? */
  2194.  
  2195.             if(type == SF_SAVE || type == SF_SCRIPT)
  2196.             {
  2197.                 BPTR    FileLock;
  2198.                 int    Len = strlen(FileName);
  2199.  
  2200.                     /* If no printer width has been defined yet,
  2201.                      * consult the system preferences settings.
  2202.                      */
  2203.  
  2204.                 if(!ScriptWidth && type == SF_SCRIPT)
  2205.                 {
  2206.                     struct Preferences Prefs;
  2207.  
  2208.                         /* Get the system preferences. */
  2209.  
  2210.                     if(GetPrefs(&Prefs,sizeof(struct Preferences)))
  2211.                     {
  2212.                             /* Adjust the width if too small. */
  2213.  
  2214.                         if((ScriptWidth = (int)Prefs . PrintRightMargin - (int)Prefs . PrintLeftMargin + 1) < MIN_PRINTER_COLUMNS)
  2215.                             ScriptWidth = MIN_PRINTER_COLUMNS;
  2216.                     }
  2217.                 }
  2218.  
  2219.                 if(type == SF_SAVE || (type == SF_SCRIPT && FileName[Len - 1] != ':'))
  2220.                 {
  2221.                         /* Does the file already exist? */
  2222.  
  2223.                     if(FileLock = Lock(FileName,ACCESS_READ))
  2224.                     {
  2225.                             /* Release the lock on it. */
  2226.  
  2227.                         UnLock(FileLock);
  2228.  
  2229.                             /* Print a warning message. */
  2230.  
  2231.                         scr_putline("You are about to write over an existing file.");
  2232.  
  2233.                             /* Really continue? */
  2234.  
  2235.                         if(scr_getline("Proceed? (Y/N) >",1,TempBuffer))
  2236.                         {
  2237.                                 /* Check */
  2238.  
  2239.                             if(toupper(TempBuffer[0]) != 'Y')
  2240.                                 return(NULL);
  2241.                         }
  2242.                         else
  2243.                             return(NULL);
  2244.                     }
  2245.  
  2246.                         /* Store the new file name. */
  2247.  
  2248.                     strcpy(buffer,FileName);
  2249.  
  2250.                         /* Open the file. */
  2251.  
  2252.                     if(type == SF_SCRIPT)
  2253.                     {
  2254.                         if(ScriptFile = fopen(buffer,"w"))
  2255.                             strcpy(ScriptFileName,buffer);
  2256.  
  2257.                         return(ScriptFile);
  2258.                     }
  2259.                     else
  2260.                         return(fopen(buffer,"wb"));
  2261.                 }
  2262.                 else
  2263.                 {
  2264.                     if(ScriptFile = fopen(buffer,"w"))
  2265.                         strcpy(ScriptFileName,buffer);
  2266.  
  2267.                     return(ScriptFile);
  2268.                 }
  2269.             }
  2270.             else
  2271.             {
  2272.                     /* Store the new file name. */
  2273.  
  2274.                 strcpy(buffer,FileName);
  2275.  
  2276.                     /* Open the file. */
  2277.  
  2278.                 return(fopen(buffer,"rb"));
  2279.             }
  2280.         }
  2281.         else
  2282.         {
  2283.                 /* Open a file without asking for a name. */
  2284.  
  2285.             switch(type)
  2286.             {
  2287.                 case SF_SCRIPT:        if(ScriptFile = fopen(buffer,"w"))
  2288.                                 strcpy(ScriptFileName,buffer);
  2289.  
  2290.                             return(ScriptFile);
  2291.  
  2292.                 case SF_SAVE:        return(fopen(buffer,"wb"));
  2293.                 case SF_RESTORE:    return(fopen(buffer,"rb"));
  2294.             }
  2295.         }
  2296.     }
  2297.  
  2298.     return(NULL);
  2299. }
  2300.  
  2301. /*
  2302.  * Function:    scr_close_sf()
  2303.  *
  2304.  * Arguments:
  2305.  *      filenm    - name of file just processed
  2306.  *      fp        - FILE* to open saved file
  2307.  *      type      - SF_SAVE     closing a saved game file
  2308.  *                  SF_RESTORE  closing a restored game file
  2309.  *                  SF_SCRIPT   closing a scripting file
  2310.  *
  2311.  * Description:
  2312.  *      This function will be called immediately after a successful
  2313.  *      save or restore of a game file, so that if the interface needs
  2314.  *      to perform any actions related to the saved game it may.  It
  2315.  *      will also be called when the interpreter notices that
  2316.  *      scripting has been turned off.  It should at least close the
  2317.  *      file.
  2318.  *
  2319.  *      This function will only be called if the save/restore of the
  2320.  *      game succeeded; if it fails the file will be closed by the
  2321.  *      interpreter.
  2322.  */
  2323.  
  2324. void
  2325. scr_close_sf(const char * filenm, FILE *fp, int type)
  2326. {
  2327.     struct DiskObject    *Icon = NULL;
  2328.     int             Len;
  2329.  
  2330.         /* Close the file. */
  2331.  
  2332.     fclose(fp);
  2333.  
  2334.         /* What are we to do? */
  2335.  
  2336.     switch(type)
  2337.     {
  2338.             /* Close a saved game file? */
  2339.  
  2340.         case SF_SAVE:
  2341.  
  2342.                 /* Clear the `executable' bit. */
  2343.  
  2344.             SetProtection((char *)filenm,FIBF_EXECUTE);
  2345.  
  2346.                 /* Get the default icon. */
  2347.  
  2348.             if(IconBase)
  2349.             {
  2350.                 if(NewOS)
  2351.                     Icon = GetDiskObject("PROGDIR:Icon.Data");
  2352.                 else
  2353.                     Icon = GetDiskObject("Icon.Data");
  2354.             }
  2355.  
  2356.                 /* Did we get any? */
  2357.  
  2358.             if(Icon)
  2359.             {
  2360.                 STRPTR *ToolTypes;
  2361.  
  2362.                     /* Create the tool type array. */
  2363.  
  2364.                 if(ToolTypes = (STRPTR *)malloc(sizeof(char *) * (NUM_FKEYS + NUM_OPTIONS + 1)))
  2365.                 {
  2366.                     int i,j = 0;
  2367.  
  2368.                         /* Fill in the file type. */
  2369.  
  2370.                     ToolTypes[j++] = "FILETYPE=BOOKMARK|ITF";
  2371.  
  2372.                         /* Add the story file name. */
  2373.  
  2374.                     if(ToolTypes[j] = (STRPTR)malloc(strlen(StoryName) + 7))
  2375.                         sprintf(ToolTypes[j++],"STORY=%s",StoryName);
  2376.  
  2377.                         /* Add the number of inter-page context lines,
  2378.                          * margin and indent settings.
  2379.                          */
  2380.  
  2381.                     if(ToolTypes[j] = (STRPTR)malloc(30))
  2382.                         sprintf(ToolTypes[j++],"CONTEXT=%d",ConLineContext);
  2383.  
  2384.                     if(ToolTypes[j] = (STRPTR)malloc(30))
  2385.                         sprintf(ToolTypes[j++],"INDENT=%d",ConLineIndent);
  2386.  
  2387.                     if(ToolTypes[j] = (STRPTR)malloc(30))
  2388.                         sprintf(ToolTypes[j++],"MARGIN=%d",ConLineMargin);
  2389.  
  2390.                         /* Take care of the remaining options. */
  2391.  
  2392.                     if(ConQueryOption(OPTION_ATTRIBUTE_ASSIGNMENTS))
  2393.                     {
  2394.                         if(ToolTypes[j] = (STRPTR)malloc(21))
  2395.                             strcpy(ToolTypes[j++],"ATTRIBUTEASSIGNMENTS");
  2396.                     }
  2397.  
  2398.                     if(ConQueryOption(OPTION_ATTRIBUTE_TESTS))
  2399.                     {
  2400.                         if(ToolTypes[j] = (STRPTR)malloc(15))
  2401.                             strcpy(ToolTypes[j++],"ATTRIBUTETESTS");
  2402.                     }
  2403.  
  2404.                     if(ConQueryOption(OPTION_ECHO))
  2405.                     {
  2406.                         if(ToolTypes[j] = (STRPTR)malloc(5))
  2407.                             strcpy(ToolTypes[j++],"ECHO");
  2408.                     }
  2409.  
  2410.                     if(!ConQueryOption(OPTION_PAGING))
  2411.                     {
  2412.                         if(ToolTypes[j] = (STRPTR)malloc(8))
  2413.                             strcpy(ToolTypes[j++],"NOPAGER");
  2414.                     }
  2415.  
  2416.                     if(ConQueryOption(OPTION_PROMPT))
  2417.                     {
  2418.                         if(ToolTypes[j] = (STRPTR)malloc(7))
  2419.                             strcpy(ToolTypes[j++],"PROMPT");
  2420.                     }
  2421.  
  2422.                     if(!ConQueryOption(OPTION_STATUS))
  2423.                     {
  2424.                         if(ToolTypes[j] = (STRPTR)malloc(9))
  2425.                             strcpy(ToolTypes[j++],"NOSTATUS");
  2426.                     }
  2427.  
  2428.                     if(ConQueryOption(OPTION_XFERS))
  2429.                     {
  2430.                         if(ToolTypes[j] = (STRPTR)malloc(10))
  2431.                             strcpy(ToolTypes[j++],"TRANSFERS");
  2432.                     }
  2433.  
  2434.                     if(ConQueryOption(OPTION_TANDY))
  2435.                     {
  2436.                         if(ToolTypes[j] = (STRPTR)malloc(6))
  2437.                             strcpy(ToolTypes[j++],"TANDY");
  2438.                     }
  2439.  
  2440.                         /* Add the function key definitions if any. */
  2441.  
  2442.                     for(i = 0 ; i < NUM_FKEYS ; i++)
  2443.                     {
  2444.                         if(FunctionKeys[i] . sb_Len)
  2445.                         {
  2446.                             if(ToolTypes[j] = (STRPTR)malloc(FunctionKeys[i] . sb_Len + 5))
  2447.                                 sprintf((char *)ToolTypes[j++],"F%02d=%s",i + 1,FunctionKeys[i] . sb_Buffer);
  2448.                         }
  2449.                     }
  2450.  
  2451.                         /* Terminate the tool type array. */
  2452.  
  2453.                     ToolTypes[j] = NULL;
  2454.  
  2455.                         /* Were we started from Workbench? */
  2456.  
  2457.                     if(WBenchMsg)
  2458.                     {
  2459.                         if(NewOS)
  2460.                         {
  2461.                                 /* Get the program directory. */
  2462.  
  2463.                             if(NameFromLock(WBenchMsg -> sm_ArgList[0] . wa_Lock,TempBuffer,MAX_FILENAME_LENGTH))
  2464.                             {
  2465.                                     /* Add the file name. */
  2466.  
  2467.                                 if(!AddPart(TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name,MAX_FILENAME_LENGTH))
  2468.                                     strcpy((char *)TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name);
  2469.                             }
  2470.                             else
  2471.                                 strcpy((char *)TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name);
  2472.                         }
  2473.                         else
  2474.                             strcpy((char *)TempBuffer,WBenchMsg -> sm_ArgList[0] . wa_Name);
  2475.                     }
  2476.                     else
  2477.                     {
  2478.                         if(NewOS)
  2479.                         {
  2480.                                 /* Get the program name. */
  2481.  
  2482.                             if(!GetProgramName(TempBuffer,MAX_FILENAME_LENGTH))
  2483.                                 strcpy((char *)TempBuffer,"Infocom");
  2484.                         }
  2485.                         else
  2486.                             strcpy((char *)TempBuffer,"Infocom");
  2487.                     }
  2488.  
  2489.                         /* Fill in the icon data. */
  2490.  
  2491.                     Icon -> do_DefaultTool    = (char *)TempBuffer;
  2492.                     Icon -> do_ToolTypes    = (char **)ToolTypes;
  2493.                     Icon -> do_StackSize    = ThisProcess -> pr_StackSize;
  2494.                     Icon -> do_CurrentX    = NO_ICON_POSITION;
  2495.                     Icon -> do_CurrentY    = NO_ICON_POSITION;
  2496.  
  2497.                         /* Create the icon. */
  2498.  
  2499.                     if(!PutDiskObject((char *)filenm,Icon))
  2500.                         scr_putmesg("Error creating icon file",TRUE);
  2501.  
  2502.                         /* Free the tool type entries. */
  2503.  
  2504.                     for(i = 1 ; i < j ; i++)
  2505.                         free(ToolTypes[i]);
  2506.  
  2507.                         /* Free the tool type array. */
  2508.  
  2509.                     free(ToolTypes);
  2510.                 }
  2511.             }
  2512.             else
  2513.                 scr_putmesg("No icon",FALSE);
  2514.  
  2515.             break;
  2516.  
  2517.                 /* Close a restored game file? */
  2518.  
  2519.         case SF_RESTORE:
  2520.  
  2521.                 /* Get the file icon. */
  2522.  
  2523.             if(IconBase)
  2524.             {
  2525.                 if(Icon = GetDiskObject((char *)filenm))
  2526.                 {
  2527.                     char     Buffer[5],
  2528.                         *Type;
  2529.                     int     i;
  2530.  
  2531.                         /* Does it have a filetype info attached? */
  2532.  
  2533.                     if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,"FILETYPE"))
  2534.                     {
  2535.                             /* Is it a bookmark file? */
  2536.  
  2537.                         if(MatchToolValue(Type,"BOOKMARK") && MatchToolValue(Type,"ITF"))
  2538.                         {
  2539.                                 /* Check for function key
  2540.                                  * defintions and set them
  2541.                                  * if approriate.
  2542.                                  */
  2543.  
  2544.                             for(i = 0 ; i < NUM_FKEYS ; i++)
  2545.                             {
  2546.                                     /* Build fkey string. */
  2547.  
  2548.                                 sprintf(Buffer,"F%02d",i + 1);
  2549.  
  2550.                                     /* See if we can find it. */
  2551.  
  2552.                                 if(Type = FindToolType((STRPTR *)Icon -> do_ToolTypes,Buffer))
  2553.                                     ConSetKey(i,Type,strlen(Type));
  2554.                                 else
  2555.                                     ConSetKey(i,"",0);
  2556.                             }
  2557.                         }
  2558.                     }
  2559.                 }
  2560.                 else
  2561.                     scr_putmesg("No icon",FALSE);
  2562.             }
  2563.             else
  2564.                 scr_putmesg("No icon",FALSE);
  2565.  
  2566.             break;
  2567.  
  2568.         /* Close a script file? */
  2569.  
  2570.     case SF_SCRIPT:
  2571.  
  2572.                 /* Clear the script file pointer. */
  2573.  
  2574.             ScriptFile = NULL;
  2575.  
  2576.                 /* Determine file name length. */
  2577.  
  2578.             Len = strlen(filenm);
  2579.  
  2580.                 /* Is this a file or a device name? */
  2581.  
  2582.             if(filenm[Len - 1] != ':')
  2583.             {
  2584.                     /* Clear the executable bit. */
  2585.  
  2586.                 SetProtection((STRPTR)filenm,FIBF_EXECUTE);
  2587.  
  2588.                     /* Try to read the story file icon. */
  2589.  
  2590.                 if(IconBase)
  2591.                 {
  2592.                     if(NewOS)
  2593.                     {
  2594.                         char *Name;
  2595.  
  2596.                             /* Try to locate the story file location... */
  2597.  
  2598.                         if(Name = ConLocateStory("",StoryName))
  2599.                             Icon = GetDiskObject(Name);
  2600.                     }
  2601.  
  2602.                         /* If everything else fails,
  2603.                          * try the default.
  2604.                          */
  2605.  
  2606.                     if(!Icon)
  2607.                         Icon = GetDiskObject("Story.Data");
  2608.                 }
  2609.  
  2610.                     /* Did we get one? */
  2611.  
  2612.                 if(Icon)
  2613.                 {
  2614.                     STATIC char *ToolTypes[] =
  2615.                     {
  2616.                         "FILETYPE=TEXT|ASCII",
  2617.                         NULL
  2618.                     };
  2619.  
  2620.                         /* Set up the default information. */
  2621.  
  2622.                     Icon -> do_DefaultTool    = "SYS:Utilities/More";
  2623.                     Icon -> do_ToolTypes    = ToolTypes;
  2624.                     Icon -> do_StackSize    = 8192;
  2625.                     Icon -> do_CurrentX    = NO_ICON_POSITION;
  2626.                     Icon -> do_CurrentY    = NO_ICON_POSITION;
  2627.  
  2628.                         /* Create the icon. */
  2629.  
  2630.                     if(!PutDiskObject((char *)filenm,Icon))
  2631.                         scr_putmesg("Error creating icon file",TRUE);
  2632.                 }
  2633.                 else
  2634.                     scr_putmesg("No icon",FALSE);
  2635.             }
  2636.  
  2637.             if(NewOS)
  2638.             {
  2639.                 struct MenuItem *Item;
  2640.  
  2641.                     /* Block the menu strip. */
  2642.  
  2643.                 ConLockMenus();
  2644.  
  2645.                     /* Change the `Script...' menu item
  2646.                      * according to the current scripting
  2647.                      * settings.
  2648.                      */
  2649.  
  2650.                 Item = ItemAddress(Menu,FULLMENUNUM(MENU_PROJECT,PROJECTMENU_SCRIPT,NOSUB));
  2651.  
  2652.                 Item -> Flags &= ~CHECKED;
  2653.  
  2654.                     /* Enable the menu strip again. */
  2655.  
  2656.                 ConUnlockMenus();
  2657.             }
  2658.  
  2659.             break;
  2660.     }
  2661.  
  2662.         /* Release the icon data. */
  2663.  
  2664.     if(Icon)
  2665.         FreeDiskObject(Icon);
  2666. }
  2667.